import { TFile, Plugin } from 'obsidian';
interface Position {
    line: number,
    offset: number
}

/**
 * 表示一个在笔记中找到的文本位置
 */
interface TextMatchResult {
    /** 匹配的起始位置 */
    start: Position;
    /** 匹配的结束位置 */
    end: Position;
    /** 匹配的完整文本内容 */
    matchedText: string;
    /** 正则表达式捕获组内容（如果有） */
    captureGroups?: string[];
    /** 匹配类型：文本或正则表达式 */
    matchType: 'text' | 'regex';
}

/**
 * 文本定位配置选项
 */
interface TextLocatorOptions {
    /** 是否区分大小写（默认false） */
    caseSensitive?: boolean;
    /** 是否精确匹配空白字符（默认true） */
    exactWhitespace?: boolean;
    /** 最大返回结果数量（默认100） */
    maxResults?: number;
    /** 是否包含捕获组信息（默认false） */
    includeCaptureGroups?: boolean;
    /** 是否启用多行模式（默认true） */
    multiline?: boolean;
}

/**
 * 高级文本定位器类 - 支持多行文本和正则表达式匹配
 */
export class AdvancedTextLocator {

    /**
     * 在笔记内容中定位文本或正则表达式匹配项
     * @param noteContent 笔记的完整内容
     * @param targetText 要查找的目标文本或正则表达式
     * @param options 配置选项
     * @returns 包含所有匹配位置信息的数组
     */
    static locateText(
        noteContent: string,
        targetText: string,
        options: TextLocatorOptions & { isRegex?: boolean } = {}
    ): TextMatchResult[] {
        const {
            caseSensitive = false,
            exactWhitespace = true,
            maxResults = 100,
            includeCaptureGroups = false,
            multiline = true,
            isRegex = false
        } = options;

        const results: TextMatchResult[] = [];

        if (!noteContent || !targetText) {
            return results;
        }

        try {
            if (isRegex) {
                // 正则表达式匹配模式
                return this.locateWithRegex(noteContent, targetText, {
                    caseSensitive,
                    maxResults,
                    includeCaptureGroups,
                    multiline
                });
            } else {
                // 普通文本匹配模式（支持多行）
                return this.locateMultiLineText(noteContent, targetText, {
                    caseSensitive,
                    exactWhitespace,
                    maxResults,
                    multiline
                });
            }
        } catch (error) {
            console.error('文本定位错误:', error);
            return results;
        }
    }

    /**
     * 正则表达式匹配实现
     */
    private static locateWithRegex(
        noteContent: string,
        regexPattern: string,
        options: Pick<TextLocatorOptions, 'caseSensitive' | 'maxResults' | 'includeCaptureGroups' | 'multiline'>
    ): TextMatchResult[] {
        const results: TextMatchResult[] = [];

        try {
            // 构建正则表达式标志
            let flags = 'g'; // 全局匹配
            if (!options.caseSensitive) flags += 'i';
            if (options.multiline) flags += 'm';

            const regex = new RegExp(regexPattern, flags);
            let match;
            let matchCount = 0;

            while ((match = regex.exec(noteContent)) !== null && matchCount < options.maxResults) {
                const startIndex = match.index;
                const matchedText = match[0];
                const endIndex = startIndex + matchedText.length - 1;

                const startPosition = this.calculateGlobalPosition(noteContent, startIndex);
                const endPosition = this.calculateGlobalPosition(noteContent, endIndex);

                const result: TextMatchResult = {
                    start: startPosition,
                    end: endPosition,
                    matchedText: matchedText,
                    matchType: 'regex'
                };

                if (options.includeCaptureGroups && match.length > 1) {
                    result.captureGroups = match.slice(1);
                }

                results.push(result);
                matchCount++;

                // 避免零长度匹配的无限循环
                if (match.index === regex.lastIndex) {
                    regex.lastIndex++;
                }
            }
        } catch (error) {
            throw new Error(`无效的正则表达式: ${error.message}`);
        }

        return results;
    }

    /**
     * 多行文本匹配实现
     */
    private static locateMultiLineText(
        noteContent: string,
        targetText: string,
        options: Pick<TextLocatorOptions, 'caseSensitive' | 'exactWhitespace' | 'maxResults' | 'multiline'>
    ): TextMatchResult[] {
        const results: TextMatchResult[] = [];

        // 预处理文本
        let searchContent = noteContent;
        let searchText = targetText;

        if (!options.caseSensitive) {
            searchContent = noteContent.toLowerCase();
            searchText = targetText.toLowerCase();
        }

        if (!options.exactWhitespace) {
            // 模糊匹配：标准化空白字符
            searchContent = this.normalizeWhitespace(searchContent);
            searchText = this.normalizeWhitespace(searchText);
        }

        const lines = searchContent.split('\n');
        const targetLines = searchText.split('\n');
        let matchCount = 0;

        // 遍历每一行，寻找匹配的起始行
        for (let i = 0; i <= lines.length - targetLines.length && matchCount < options.maxResults; i++) {
            let matched = true;

            // 检查后续行是否匹配
            for (let j = 0; j < targetLines.length; j++) {
                const lineToCheck = options.exactWhitespace ?
                    lines[i + j] :
                    this.normalizeWhitespace(lines[i + j]);

                const targetLine = options.exactWhitespace ?
                    targetLines[j] :
                    this.normalizeWhitespace(targetLines[j]);

                if (lineToCheck !== targetLine) {
                    matched = false;
                    break;
                }
            }

            if (matched) {
                // 计算位置信息（使用原始内容）
                const originalLines = noteContent.split('\n');
                const startCharIndex = this.calculateCharIndex(originalLines, i, 0);
                const endLineIndex = i + targetLines.length - 1;
                const endCharIndex = this.calculateCharIndex(originalLines, endLineIndex,
                    originalLines[endLineIndex].length);

                const startPosition = this.calculateGlobalPosition(noteContent, startCharIndex);
                const endPosition = this.calculateGlobalPosition(noteContent, endCharIndex);

                // 重建匹配的文本（使用原始内容）
                const matchedText = originalLines
                    .slice(i, i + targetLines.length)
                    .join('\n');

                results.push({
                    start: startPosition,
                    end: endPosition,
                    matchedText: matchedText,
                    matchType: 'text'
                });

                matchCount++;
                // 跳过已经匹配的行，避免重叠匹配
                i += targetLines.length - 1;
            }
        }

        return results;
    }

    /**
     * 标准化空白字符（用于模糊匹配）
     */
    private static normalizeWhitespace(text: string): string {
        return text.replace(/\s+/g, ' ').trim();
    }

    /**
     * 计算指定行和列在完整内容中的字符索引
     */
    private static calculateCharIndex(lines: string[], lineIndex: number, columnIndex: number): number {
        let charIndex = 0;
        for (let i = 0; i < lineIndex; i++) {
            charIndex += lines[i].length + 1; // +1 用于换行符
        }
        return charIndex + columnIndex;
    }

    /**
     * 计算指定字符索引在全文中的位置（line和全局offset）
     * @param content 完整文本内容
     * @param charIndex 字符索引（全文偏移量）
     * @returns Position对象，line为行号，offset为全文偏移量
     */
    private static calculateGlobalPosition(content: string, charIndex: number): Position {
        // 边界检查
        if (charIndex < 0) charIndex = 0;
        if (charIndex >= content.length) charIndex = content.length - 1;

        let currentIndex = 0;
        let lineNumber = 0;

        const lines = content.split('\n');
        for (let i = 0; i < lines.length; i++) {
            const lineLength = lines[i].length;

            // 检查字符索引是否在当前行范围内
            if (charIndex < currentIndex + lineLength + 1) {
                lineNumber = i;
                break;
            }

            currentIndex += lineLength + 1; // +1 用于换行符
        }

        // 关键修改：offset现在表示全文偏移量
        return {
            line: lineNumber,
            offset: charIndex
        };
    }

    /**
     * 根据字符索引计算在文本中的位置（行号和偏移量）
     */
    private static calculatePosition(content: string, charIndex: number): Position {
        // 边界检查
        if (charIndex < 0) charIndex = 0;
        if (charIndex >= content.length) charIndex = content.length - 1;

        let currentIndex = 0;
        let lineNumber = 0;

        const lines = content.split('\n');
        for (let i = 0; i < lines.length; i++) {
            const lineLength = lines[i].length;

            if (charIndex < currentIndex + lineLength + 1) { // +1 考虑换行符
                lineNumber = i;
                break;
            }

            currentIndex += lineLength + 1; // +1 用于换行符
        }

        const offsetInLine = charIndex - currentIndex;

        return {
            line: lineNumber,
            offset: offsetInLine
        };
    }

    /**
     * 验证正则表达式是否有效
     */
    static validateRegex(pattern: string): { isValid: boolean; error?: string } {
        try {
            new RegExp(pattern);
            return { isValid: true };
        } catch (error) {
            return {
                isValid: false,
                error: error instanceof Error ? error.message : '未知错误'
            };
        }
    }
}

/**
 * 预定义的正则表达式模式库
 */
export const CommonRegexPatterns = {
    // 日期和时间
    ISO_DATE: /\d{4}-\d{2}-\d{2}/g,
    TIME_12H: /\b(1[0-2]|0?[1-9]):[0-5][0-9]\s*(AM|PM)/gi,
    TIME_24H: /\b([01]?[0-9]|2[0-3]):[0-5][0-9]/g,

    // 联系信息
    EMAIL: /\b[\w.%+-]+@[\w.-]+\.[A-Z]{2,}\b/gi,
    PHONE: /\b(\+\d{1,3}[-.]?)?\(?\d{3}\)?[-.]?\d{3}[-.]?\d{4}\b/g,
    URL: /https?:\/\/[^\s]+/gi,

    // Obsidian特定元素
    WIKI_LINK: /\[\[[^[\]]+?\]\]/g,
    MARKDOWN_LINK: /\[[^[\]]*?\]\([^)]+\)/g,
    TAG: /(?<=^|\s)#[^\s#]+/g,
    HEADING: /^#{1,6}\s+.+$/gm,

    // 代码相关
    TODO: /TODO:\s*(.+)$/gim,
    FIXME: /FIXME:\s*(.+)$/gim,
    CODE_BLOCK: /```[\s\S]*?```/g,

    // 数字和货币
    NUMBER: /\b\d+\b/g,
    CURRENCY: /\$\d+(?:\.\d{2})?/g
};

/**
 * 在Obsidian插件中使用文本定位器的示例插件
 */
export class TextLocatorPlugin extends Plugin {
    /**
     * 在活动文件中查找文本
     */
    async locateInActiveFile(targetText: string, options: TextLocatorOptions & { isRegex?: boolean } = {}) {
        const activeFile = this.app.workspace.getActiveFile();
        if (!activeFile) {
            throw new Error('没有活动的文件');
        }

        if (activeFile.extension !== 'md') {
            throw new Error('只能在Markdown文件中查找');
        }

        const content = await this.app.vault.read(activeFile);
        return AdvancedTextLocator.locateText(content, targetText, options);
    }

    /**
     * 在指定文件中查找文本
     */
    async locateInFile(file: TFile, targetText: string, options: TextLocatorOptions & { isRegex?: boolean } = {}) {
        const content = await this.app.vault.read(file);
        return AdvancedTextLocator.locateText(content, targetText, options);
    }

    /**
     * 在多个文件中查找文本
     */
    async locateInFiles(files: TFile[], targetText: string, options: TextLocatorOptions & { isRegex?: boolean } = {}) {
        const results: Array<{ file: TFile; matches: TextMatchResult[] }> = [];

        for (const file of files) {
            if (file.extension === 'md') {
                const matches = await this.locateInFile(file, targetText, options);
                if (matches.length > 0) {
                    results.push({ file, matches });
                }
            }
        }

        return results;
    }

    /**
     * 高亮显示匹配的文本（在编辑器中）
     */
    async highlightMatchesInEditor(matches: TextMatchResult[]) {
        const activeLeaf = this.app.workspace.activeLeaf;
        if (activeLeaf && activeLeaf.view.getViewType() === 'markdown') {
            // 这里可以实现编辑器高亮逻辑
            matches.forEach(match => {
                console.log(`高亮显示: 行 ${match.start.line + 1}-${match.end.line + 1}`);
                // 实际的高亮实现需要调用Obsidian的编辑器API
            });
        }
    }
}

// 使用示例和测试函数
export class TextLocatorExamples {
    /**
     * 演示基本使用方法
     */
    static demonstrateBasicUsage() {
        const sampleContent = `# 项目计划

## 第一阶段
- 完成需求分析 (优先级: 高)
- 设计系统架构 (优先级: 中)
- 编写技术文档 (优先级: 低)

## 第二阶段
- 开发核心功能 (优先级: 高)
- 进行单元测试 (优先级: 中)`;

        console.log('=== 示例1: 多行文本匹配 ===');
        const multiLineResults = AdvancedTextLocator.locateText(
            sampleContent,
            '## 第一阶段\n- 完成需求分析\n- 设计系统架构',
            { isRegex: false }
        );

        multiLineResults.forEach((result, index) => {
            console.log(`匹配项 ${index + 1}:`);
            console.log(`位置: 行 ${result.start.line + 1}-${result.end.line + 1}`);
            console.log(`文本:\n${result.matchedText}`);
        });

        console.log('\n=== 示例2: 正则表达式匹配 ===');
        const regexResults = AdvancedTextLocator.locateText(
            sampleContent,
            '优先级:\\s*(高|中|低)',
            { isRegex: true, includeCaptureGroups: true }
        );

        regexResults.forEach((result, index) => {
            console.log(`匹配项 ${index + 1}:`);
            console.log(`位置: 行 ${result.start.line + 1}, 列 ${result.start.offset + 1}`);
            console.log(`捕获组: ${result.captureGroups?.join(', ')}`);
        });

        console.log('\n=== 示例3: 使用预定义模式 ===');
        const todoResults = AdvancedTextLocator.locateText(
            sampleContent,
            CommonRegexPatterns.TODO.source,
            { isRegex: true }
        );
    }

    /**
     * 演示在Obsidian插件中的集成
     */
    static async demonstratePluginIntegration(plugin: TextLocatorPlugin) {
        try {
            // 在当前活动文件中查找TODO项
            const todoMatches = await plugin.locateInActiveFile(
                CommonRegexPatterns.TODO.source,
                { isRegex: true, caseSensitive: false }
            );

            if (todoMatches.length > 0) {
                console.log(`找到 ${todoMatches.length} 个TODO项:`);
                todoMatches.forEach(match => {
                    console.log(`- 行 ${match.start.line + 1}: ${match.matchedText}`);
                });

                // 高亮显示匹配项
                await plugin.highlightMatchesInEditor(todoMatches);
            } else {
                console.log('未找到TODO项');
            }

        } catch (error) {
            console.error('查找失败:', error);
        }
    }
}

// 导出类型和接口供外部使用
export type { TextMatchResult, TextLocatorOptions };